[LG4314]-CPU监控

题目链接

AC之旅真是坎坷啊。。一上来,咦,这不是模版题嘛,深蓝题是群众误评嘛 qwq

然后敲完一交,哎哟啧,爆零哇。。。去翻了翻题解,发现这个问题还真是隐蔽。

题解里是这样说的:

“按原来的方法会有一点 bug ,就是很有可能会出现这样的情况:对于某个结点 i ,在它的标记还没有下放的时候,它的父亲又下放了新的标记给它,于是就将原来的标记覆盖了,丢失了原来的那一次修改的值,这样在查询历史最大值的时候就有可能出现错误的答案。

“如果只记录区间历史最大值显然不能下放,如果单纯更新区间加,区间赋值最大值,可能会出现历史最大值更新不及时的情况。如先赋值很大值,未来得及下放,又赋值很小,导致子区间历史最大值不能更新。又如如果区间加只取最大值,可能会只取最大值,导致实际上忽视了一些使区间加变小的操作。”

如果次次下放标记,那显然复杂度太高了。

为了不错过每一次操作产生的贡献,我们对于每一个区间 $x$ 存储它从上一次 pushdown 到现在的最大加法操作和最大赋值操作,这样显然是正确的。

总之还是很棒的啊,至少比之前的所以模版题好!!!就是要做这样的(虐)题 ( ´▽`)

code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
const int N = 1e5 + 10, inf = 1e9;
int n, m;
char s[5];

struct node {
ll add, c;
ll mx, hx;
ll ha, hc; // h = history
}t[N << 2];

void pushup(int x) {
t[x].mx = max(t[x << 1].mx, t[x << 1 | 1].mx);
t[x].hx = max(t[x << 1].hx, t[x << 1 | 1].hx);
}

void psd(int x) {
for (int i = 0; i <= 1; i++) {
int s = x << 1 | i; // s = son
t[s].hx = max(t[s].hx, max(t[s].mx + t[x].ha, t[x].hc));
if (t[s].c != -inf)
t[s].hc = max(t[s].hc, t[s].c + t[x].ha);
else t[s].ha = max(t[s].ha, t[s].add + t[x].ha);
if (t[x].add) {
if (t[s].c != -inf) t[s].c += t[x].add;
else t[s].add += t[x].add;
t[s].mx += t[x].add;
}
if (t[x].c != -inf) {
t[s].mx = t[s].c = t[x].c;
t[s].add = 0;
}
t[s].hc = max(t[s].hc, max(t[s].c, t[x].hc));
t[s].ha = max(t[s].ha, t[s].add);
}
t[x].hc = t[x].c = -inf;
t[x].add = t[x].ha = 0;
}

void build(int x, int l, int r) {
t[x].add = t[x].ha = 0;
t[x].c = t[x].hc = -inf;
if (l == r) {
ll tmp; scanf("%lld", &tmp);
t[x].mx = t[x].hx = tmp;
return;
}
int mid = (l + r) >> 1;
build(x << 1, l, mid);
build(x << 1 | 1, mid + 1, r);
pushup(x);
}

void modify(int x, int l, int r, int lx, int rx, ll val) {
if (l < r) psd(x);
if (lx <= l && r <= rx) {
t[x].mx += val;
t[x].add += val;
t[x].ha += val;
t[x].hx = max(t[x].hx, t[x].mx);
return;
}
int mid = (l + r) >> 1;
if (lx <= mid) modify(x << 1, l, mid, lx, rx, val);
if (rx > mid) modify(x << 1 | 1, mid + 1, r, lx, rx, val);
pushup(x);
}

void change(int x, int l, int r, int lx, int rx, ll val) {
if (l != r) psd(x);
if (lx <= l && r <= rx) {
t[x].c = val;
t[x].mx = val;
t[x].hc = val;
t[x].hx = max(t[x].hx, val);
return;
}
int mid = (l + r) >> 1;
if (lx <= mid) change(x << 1, l, mid, lx, rx, val);
if (rx > mid) change(x << 1 | 1, mid + 1, r, lx, rx, val);
pushup(x);
}

ll queryhis(int x, int l, int r, int lx, int rx) {
if (l < r) psd(x);
if (lx <= l && r <= rx) return t[x].hx;
int mid = (l + r) >> 1;
ll sum = -1e9;
if (lx <= mid) sum = queryhis(x << 1, l, mid, lx, rx);
if (rx > mid) sum = max(sum, queryhis(x << 1 | 1, mid + 1, r, lx, rx));
return sum;
}

ll querynow(int x, int l, int r, int lx, int rx) {
if (l < r) psd(x);
if (lx <= l && r <= rx) return t[x].mx;
int mid = (l + r) >> 1;
ll sum = -1e9;
if (lx <= mid) sum = querynow(x << 1, l, mid, lx, rx);
if (rx > mid) sum = max(sum, querynow(x << 1 | 1, mid + 1, r, lx, rx));
return sum;
}

int main() {
scanf("%d", &n);
build(1, 1, n);
scanf("%d", &m);
while (m--) {
scanf("%s", s);
if (s[0] == 'A') {
int l, r; scanf("%d%d", &l, &r);
printf("%d\n", queryhis(1, 1, n, l, r));
} else if (s[0] == 'Q') {
int l, r; scanf("%d%d", &l, &r);
printf("%d\n", querynow(1, 1, n, l, r));
} else if (s[0] == 'P') {
int l, r, z; scanf("%d%d%d", &l, &r, &z);
modify(1, 1, n, l, r, z);
} else {
int l, r, z; scanf("%d%d%d", &l, &r, &z);
change(1, 1, n, l, r, z);
}
}
return 0;
}